#include <iostream>
#include <vector>
#include <stdexcept>
using namespace std;

class queue
{
private:
    vector<int> data;
    int _size;
    int _num;
    int _front;
    int _rear;

public:
    queue(int size)
    {
        _size = size;
        _num = 0;
        _front = 0;
        _rear = -1;
        data.resize(size);
    }

    bool is_empty()
    {
        return _num == 0;
    }

    bool is_full()
    {
        return _num == _size;
    }

    void enqueue(int val)
    {
        if (is_full())
        {
            cerr << "queue is full" << endl;
            throw runtime_error("queue is full");
        }
        _rear += 1;
        data[_rear] = val;

        _num++;
    }

    int dequeue()
    {
        if (is_empty())
        {
            cerr << "queue is empty" << endl;
            throw runtime_error("queue is empty");
        }
        int val = data[_front];
        data[_front] = 0; // 清空数据
        _front += 1;

        _num--;
        if (_num == 0) // 重置队列
        {
            cout << "reset queue" << endl;
            _front = 0;
            _rear = -1;
        }
        return val;
    }

    int get_front()
    {
        if (is_empty())
        {
            cerr << "queue is full" << endl;
            throw runtime_error("queue is empty");
        }
        return data[_front];
    }

    int get_rear()
    {
        if (is_empty())
        {
            cerr << "queue is empty" << endl;
            throw runtime_error("queue is empty");
        }
        return data[_rear];
    }

    void show()
    {
        cout << "queue: [";
        for (auto it : data)
        {
            cout << " " << it;
        }
        cout << "] " << endl;
    }
};

int main(void)
{
    queue q(5);
    q.enqueue(1);
    q.enqueue(2);
    q.enqueue(3);
    q.enqueue(4);
    q.enqueue(5);
    try
    {
        q.enqueue(6);
    }
    catch (const std::exception &e)
    {
        std::cerr << "Caught exception: " << e.what() << '\n';
    }

    // 1.入队列
    cout << "\n---1.入队列---" << endl;
    q.show();
    cout << q.get_front() << endl;
    cout << q.get_rear() << endl;

    // 2.出队列
    cout << "\n---2.出队列---" << endl;
    int val;
    val = q.dequeue();
    cout << "dequeue: " << val << endl;
    q.show();
    cout << q.get_front() << endl;
    cout << q.get_rear() << endl;

    // 3.完全出队列
    cout << "\n---3.完全出队列---" << endl;
    while (q.is_empty() == false)
    {
        val = q.dequeue();
        cout << "dequeue: " << val << endl;
    }
    q.show();

    // 3.完全出队列
    cout << "\n---3.完全出队列---" << endl;
    while (q.is_empty() == false)
    {
        val = q.dequeue();
        cout << "dequeue: " << val << endl;
    }
    q.show();

    // 4.再入队列
    cout << "\n---4.再入队列---" << endl;
    q.enqueue(7);
    q.show();
    cout << q.get_front() << endl;
    cout << q.get_rear() << endl;

    return 0;
}